package com.unionpay.acp.service.consume;

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.eastdigit.servlet.ReqBean;
import com.eastdigit.system.service.BaseService;
import com.gjzt.business.bid.inter.BiddingMapper;
import com.gjzt.business.bid.model.Bidding;
import com.gjzt.business.depositOrder.inter.DepositOrderMapper;
import com.gjzt.business.depositOrder.model.DepositOrder;
import com.gjzt.business.depositOrder.service.DepositOrderService;
import com.gjzt.business.utils.Constant;
import com.unionpay.acp.sdk.AcpService;
import com.unionpay.acp.sdk.LogUtil;
import com.unionpay.acp.sdk.SDKConfig;
import com.unionpay.acp.service.PayTools;

/**
 * 重要：联调测试时请仔细阅读注释！
 * 
 * 产品：跳转网关支付产品<br>
 * 交易：消费：前台跳转，有前台通知应答和后台通知应答<br>
 * 日期： 2015-09<br>
 * 版本： 1.0.0 版权： 中国银联<br>
 * 说明：以下代码只是为了方便商户测试而提供的样例代码，商户可以根据自己需要，按照技术文档编写。该代码仅供参考，不提供编码性能规范性等方面的保障<br>
 * 提示：该接口参考文档位置：open.unionpay.com帮助中心 下载 产品接口规范 《网关支付产品接口规范》，<br>
 * 《平台接入接口规范-第5部分-附录》（内包含应答码接口规范，全渠道平台银行名称-简码对照表)<br>
 * 《全渠道平台接入接口规范 第3部分 文件接口》（对账文件格式说明）<br>
 * 测试过程中的如果遇到疑问或问题您可以：1）优先在open平台中查找答案： 调试过程中的问题或其他问题请在
 * https://open.unionpay.com/ajweb/help/faq/list 帮助中心 FAQ 搜索解决方案
 * 测试过程中产生的6位应答码问题疑问请在https://open.unionpay.com/ajweb/help/respCode/respCodeList
 * 输入应答码搜索解决方案 2） 咨询在线人工支持： open.unionpay.com注册一个用户并登陆在右上角点击“在线客服”，咨询人工QQ测试支持。
 * 交易说明:1）以后台通知或交易状态查询交易确定交易成功,前台通知不能作为判断成功的标准.
 * 2）交易状态查询交易（Form_6_5_Query）建议调用机制：前台类交易建议间隔（5分、10分、30分、60分、120分）发起交易查询，
 * 如果查询到结果成功，则不用再查询。（失败，处理中，查询不到订单均可能为中间状态）。也可以建议商户使用payTimeout（支付超时时间），
 * 过了这个时间点查询，得到的结果为最终结果。
 */

@Service
public class FrontConsume extends BaseService {

	@Autowired
	private BiddingMapper biddingMapper;
	@Autowired
	private DepositOrderService depositOrderService;
	@Autowired
	private DepositOrderMapper depositOrderMapper;

	/**
	 * 支付保证金接口
	 * 
	 * @param req
	 * @param resp
	 * @throws ServletException
	 * @throws IOException
	 */
	public void payDeposit(ReqBean reqBean, HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		String bidId = reqBean.getInfo("bidId");
		String customerId = reqBean.getInfo("customerId");
		Bidding bid = biddingMapper.selectByPrimaryKey(bidId);

		// 前台页面传过来的
		// String merId = req.getParameter("merId");
		String merId = PayTools.merId;// 测试商户号
		// String txnAmt = req.getParameter("txnAmt");
		// String txnAmt =String.valueOf(bid.getDeposit()) ;// 获取当前竞价单需要交付的保证金
		String txnAmt = "1"; // 单位分
		double money = Double.valueOf(txnAmt) * 0.01;
		String moneyStr = String.valueOf(money);//
		// String orderId = PayTools.getOrderId(bidId, customerId);
		String txnType = "01";
		String txnTime = PayTools.getCurrentTime();
		String channelType = "07";
		String currencyCode = "156";

		DepositOrder depositOrder = depositOrderMapper.selectByBidIdAndCustomerId(bidId, customerId);
		if (null == depositOrder) {
			// 生成订单数据
			depositOrder = new DepositOrder(intIncrementId("AD_DEPOSIT_ORDER", "ID"),
					PayTools.getOrderId(bidId, customerId), txnType, moneyStr, txnTime, channelType, currencyCode,
					bidId, customerId, Constant.DEPOSIT_ORDER_STATUS_PAY_WANT, "待支付", new Date());
			depositOrderMapper.insert(depositOrder);
		} else if (Constant.DEPOSIT_ORDER_STATUS_PAY_WANT.equals(depositOrder.getOrderStatus())
				|| Constant.DEPOSIT_ORDER_STATUS_PAY_FAIL.equals(depositOrder.getOrderStatus())) {// 待支付、支付失败
			// 银联订单号查询订单不为空时更新此次订单创建时间
			depositOrderService.updateOrderMakeTime(depositOrder.getOrderId(),txnTime);
		}

		if (Constant.DEPOSIT_ORDER_STATUS_PAY_WANT.equals(depositOrder.getOrderStatus())
				|| Constant.DEPOSIT_ORDER_STATUS_PAY_FAIL.equals(depositOrder.getOrderStatus())) {// 待支付、支付失败
			Map<String, String> requestData = new HashMap<String, String>();

			/*** 银联全渠道系统，产品参数，除了encoding自行选择外其他不需修改 ***/
			requestData.put("version", PayTools.version); // 版本号，全渠道默认值
			requestData.put("encoding", PayTools.encoding_UTF8); // 字符集编码，可以使用UTF-8,GBK两种方式
			requestData.put("signMethod", "01"); // 签名方法，只支持 01：RSA方式证书加密
			requestData.put("txnType", txnType); // 交易类型 ，01：消费
			requestData.put("txnSubType", "01"); // 交易子类型， 01：自助消费
			requestData.put("bizType", "000201"); // 业务类型，B2C网关支付，手机wap支付
			requestData.put("channelType", channelType); // 渠道类型，这个字段区分B2C网关支付和手机wap支付；07：PC,平板08：手机

			/*** 商户接入参数 ***/
			requestData.put("merId", merId); // 商户号码
			requestData.put("accessType", "0"); // 接入类型，0：直连商户
			requestData.put("orderId", depositOrder.getOrderId());// 商户订单号，8-40位数字字母，不能含“-”或“_”，可以自行定制规则
			requestData.put("txnTime", txnTime); // 订单发送时间，
			requestData.put("currencyCode", currencyCode); // 交易币种（境内商户一般是156人民币）
			requestData.put("txnAmt", txnAmt); // 交易金额，单位分，不要带小数点
			requestData.put("reqReserved", bidId); // 请求方保留域，
			requestData.put("frontUrl", PayTools.frontUrl);
			requestData.put("backUrl", PayTools.backUrl);

			/** 请求参数设置完毕，以下对请求参数进行签名并生成html表单，将表单写入浏览器跳转打开银联页面 **/
			Map<String, String> submitFromData = AcpService.sign(requestData, PayTools.encoding_UTF8); // 报文中certId,signature的值是在signData方法中获取并自动赋值的，只要证书配置正确即可。

			String requestFrontUrl = SDKConfig.getConfig().getFrontRequestUrl(); // 获取请求银联的前台地址：对应属性文件acp_sdk.properties文件中的acpsdk.frontTransUrl
			String html = AcpService.createAutoFormHtml(requestFrontUrl, submitFromData, PayTools.encoding_UTF8); // 生成自动跳转的Html表单
			LogUtil.writeLog("打印请求HTML，此为请求报文，为联调排查问题的依据：" + html);
			// 将生成的html写到浏览器中完成自动跳转打开银联支付页面；这里调用signData之后，将html写到浏览器跳转到银联页面之前均不能对html中的表单项的名称和值进行修改，如果修改会导致验签不通过
			resp.getWriter().write(html);
		} else {//  1：支付成功 2、支付中 3、订单取消 4、申请退款 5：退款成功 6、退款失败（暂时没有退款业务）
			resp.setCharacterEncoding("UTF_8");// 设置Response的编码方式为UTF-8
			resp.setHeader("Content-type", "text/html;charset=UTF-8");
			resp.getWriter().write("订单已支付，请勿重复支付!");
			// resp.getWriter().write("Order has been paid, please do not repeat
			// payment!");
		}
	}
}
